// Copyright (c) 2008 Matthew Johnson
// Licensed under the MIT License (see license.txt)
package actionml {
	import actionml.core.*;
	
	import flash.display.Sprite;
	import flash.display.Stage;
	
	public dynamic class Global {
		private static var _document:flash.display.Sprite;
		private static var _initialized:Object = {};
		private static var _tags:Array = [];
		private static var _specialKeys:Object = {};

		public static function initialize(document:flash.display.Sprite, ...extensionClasses) {
			if (!_document) {
				_document = document;
			}
			Global.initializeExtensions.apply(null, Global.defaultExtensions)
			Global.initializeExtensions.apply(null, extensionClasses);
		}
		public static function get tags():Array {
			return _tags;
		}
		public static function get document():flash.display.Sprite {
			return _document;
		}
		public static function get stage():flash.display.Stage {
			return _document.stage;
		}
		public static function get swfURL():String {
			return _document.stage.root.loaderInfo.url;
		}
		public static function get swfServerRelativeURL():String {
			return _document.stage.root.loaderInfo.url.replace(/^http:\/\/[^\/]*/, "");
		}
		public static function get swfPath():String {
			return _document.stage.root.loaderInfo.url.replace(/\/[^\/]*$/, "");
		}
		public static function get swfServerRelativePath():String {
			return swfPath.replace(/^http:\/\/[^\/]*/, "");
		}
		public static function get specialKeys():Object {
			return _specialKeys;
		}
		public static function get defaultExtensions():Array {
			return [
				// the following are required in order to function
				//ObjectMethods, 
				//ClassMethods
				ArrayMethods,
				ClassMethods,
				DictionaryMethods,
				LoadingUtils,
				NumberMethods,
				ObjectIterationMethods,
				ObjectMethods,
				RegExpMethods,
				StringMethods,
				StringPathMethods,
				XMLMethods
			];
		}
		public static function initializeExtensions(...extensionClasses):void {
			if (extensionClasses) {
				for each (var extensionClass:Class in extensionClasses) {
					//Global.initializeExtension(extensionClass);
					extensionClass["initialize"]();
				}
			}
		}
		public static function initializeExtension(extensionClass:Class, extendedClass:Class = null):void {
			if (extendedClass == null) {
				if (extensionClass["extendedClass"] != null && extensionClass["extendedClass"] != undefined) {
					extendedClass = extensionClass["extendedClass"];
				} else {
					var extendedClassName:String = Object(extensionClass).toString()
						.replace(/^.*::/, "")
						.replace(/\[class /, "")
						.replace(/Methods/, "")
						.replace(/\]/, "");
					extendedClass = ClassMethods.staticMethods.forName(extendedClassName);
				}
			}
			if (extendedClass != null) {
				if (_initialized[Object(extensionClass).toString() + Object(extendedClass).toString()]) { 
					return;
				}
				for (var staticMethod:String in extensionClass.staticMethods ) {
					extendedClass[staticMethod] = extensionClass.staticMethods[staticMethod];
					Object(extendedClass).setPropertyIsEnumerable(staticMethod, false);						
				}
				for (var instanceMethod:String in extensionClass.instanceMethods) {
					extendedClass.prototype[instanceMethod] = extensionClass.instanceMethods[instanceMethod];
					extendedClass.prototype.setPropertyIsEnumerable(instanceMethod, false);
					if (instanceMethod.match(/^make/)) {
						_tags.push(instanceMethod);
					}
				}				
				_initialized[Object(extensionClass).toString() + Object(extendedClass).toString()] = true;
			}
		}
	}
}